/*******************************************************************************
 * Copyright 2009 DCSpectrometer - http://code.google.com/p/dcspectrometer 
 *  
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0 
 *     
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 *******************************************************************************/
package com.dcspectrometer;

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.util.ArrayList;

public abstract class Detector {
  /**
   * Executes feature detector on an image
   * 
   * @param image
   *          image to perform evaluation on
   * @param x
   *          x coordinate of the top left corner of area to be evaluated.
   * @param y
   *          y coordinate of the top left corner of area to be evaluated.
   * @param width
   *          width of the area to be evaluated.
   * @param height
   *          height of the area to be evaluated.
   * @return true - if feature is detected, false - otherwise.
   */
  public abstract boolean detectFeature(BufferedImage image, int x, int y, int width, int height);

  public BufferedImage showFeatures(BufferedImage image, int detectorWidth, int detectorHeight,
      int markRGB) {
    BufferedImage markedImage = new BufferedImage(image.getWidth(), image.getHeight(),
        BufferedImage.TYPE_INT_RGB);

    for (int i = 0; i < (image.getWidth() / detectorWidth) - 1; i++) {
      for (int j = 0; j < (image.getHeight() / detectorHeight) - 1; j++) {
        int x = i * detectorWidth;
        int y = j * detectorHeight;
        boolean detectorResult = detectFeature(image, x, y, detectorWidth, detectorHeight);
        if (detectorResult) {
          for (int m = 0; m < detectorWidth; m++) {
            for (int n = 0; n < detectorHeight; n++) {
              markedImage.setRGB(x + m, y + n, markRGB);
            }
          }
        } else {
          Raster nextRaster = image.getData(new Rectangle(x, y, detectorWidth, detectorHeight));

          for (int m = 0; m < detectorWidth; m++) {
            for (int n = 0; n < detectorHeight; n++) {
              int nextColor = (new Color(nextRaster.getSample(x + m, y + n, 0) / 256, nextRaster
                  .getSample(x + m, y + n, 1) / 256, nextRaster.getSample(x + m, y + n, 2) / 256))
                  .getRGB();
              markedImage.setRGB(x + m, y + n, nextColor);
            }
          }
        }
      }
    }

    return markedImage;
  }

  public ArrayList<Point> getFeatures(BufferedImage image, int detectorWidth, int detectorHeight) {
    
    ArrayList<Point> features = new ArrayList<Point>();

    for (int i = 0; i < (image.getWidth() / detectorWidth) - 1; i++) {
      for (int j = 0; j < (image.getHeight() / detectorHeight) - 1; j++) {
        int x = i * detectorWidth;
        int y = j * detectorHeight;
        boolean detectorResult = detectFeature(image, x, y, detectorWidth, detectorHeight);
        
        if(detectorResult) {
          features.add(new Point(x + (detectorWidth / 2), y + (detectorHeight / 2)));
        }
      }
    }

    return features;
  }
}
